package org.hackystat.devcathlon.ui.page.profile;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.image.resource.BufferedDynamicImageResource;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.hackystat.devcathlon.engine.profile.Profile;
import org.hackystat.devcathlon.engine.team.Team;
import org.hackystat.devcathlon.ui.DevcathlonSession;
import org.hackystat.devcathlon.ui.page.commons.panels.InfoBoxPanel;
import org.hackystat.devcathlon.ui.page.teams.profile.TeamMatchesPanel;

/**
 * Profile panel class that encapsulates units of a profile page. 
 * @author Anthony Du
 *
 */
public class ProfilePanel extends Panel {
  /** Support serialization. */
  private static final long serialVersionUID = 1L;
  
  /** The full name of the user. */
  protected String fullName = "[full name]";
  /** The screen name of the user. */
  protected String screenName = "[screen name]";
  /** The email address of the user. */
  protected String emailAddress = "[email]";
  /** The user location. */
  protected String userLocation = "[location]";
  /** The contact information of the user. */
  protected String contact = "[contact]";
  /** The user's bio info. */
  protected String bioInfo = "[bio info]";
  /** The user's gender. */
  protected String gender = "[gender]";
  /** Info Box Panel constant. */
  private String infoBoxContentId = InfoBoxPanel.contentID;
  
  /**
   * Profile panel constructor.
   * @param id unique panel id
   */
  public ProfilePanel(String id) {
    super(id);
    /** Profile session. */
    ProfileSession session = DevcathlonSession.get().getProfileSession();
    /** The session state for this page. */
    Profile profile = session.getProfile();
    fullName = profile.getFullName();
    screenName = profile.getScreenName();
    emailAddress = profile.getEmails().toString();
    bioInfo = profile.getBioInfo();
    gender = profile.getGender();
    contact = profile.getContact();
    userLocation = profile.getLocation();
    
    /* Personal details */
    add(new InfoBoxPanel("personalInfoPanel", "Personal Info") {
      /** Support serialization. */
      private static final long serialVersionUID = 1L;
      
      @Override
      protected void createContent() {
        add(new PersonalContentFragment(infoBoxContentId));
      }
    });
    
    /* Teams listing */
    final List<Team> teams = session.getTeams();
    add(new InfoBoxPanel("teamsPanel", "Team Memberships") {
      /** Support serialization. */
      private static final long serialVersionUID = 1L;

      @Override
      protected void createContent() {
        add(new TeamListingPanel(infoBoxContentId, teams));
      }
    });
    
    /* Recent events listing */
    final List<String> eventCols = new ArrayList<String>();
    eventCols.add("Event name");
    eventCols.add("Datetime");
//    add(new InfoBoxPanel("recentEventsPanel", "Recent Events") {
//      /** Support serialization. */
//      private static final long serialVersionUID = 1L;
//      
//      @Override
//      protected void createContent() {
//        add(new TableContentFragment(infoBoxContentId, eventCols, null));
//      }
//    });
    
    /* Match listing */
    if (!teams.isEmpty()) {
      DevcathlonSession.get().getTeamsSession().setSelectedTeam(teams.get(0).getName());
    }
    add(new TeamMatchesPanel("matchesPanel"));
    
    /* Bio Info details */
    add(new InfoBoxPanel("bioInfoPanel", "Bio Info") {
      /** Support serialization. */
      private static final long serialVersionUID = 1L;
      
      @Override
      protected void createContent() {
       add(new TextBoxFragment(infoBoxContentId, bioInfo)); 
      }
    });
    
  }
  
  /**
   * Profile content fragment that details a user's profile.
   * @author Anthony Du
   */
  public class PersonalContentFragment extends Fragment {
    /** Support serialization. */
    private static final long serialVersionUID = 1L;
    private final List<CommonListItem> personalItems = new ArrayList<CommonListItem>();
    
    /**
     * Personal Content Fragment.
     * @param id unique fragment id
     */
    public PersonalContentFragment(String id) {
      super(id, "personalContentFragment", ProfilePanel.this);
      addAvatar();
      addInfo();
    }
    
    /**
     * Add avatar image.
     */
    private void addAvatar() {
      Profile profile = DevcathlonSession.get().getProfileSession().getProfile();
      try {
        BufferedDynamicImageResource resource = new BufferedDynamicImageResource();     
        BufferedImage image;      
        image = ImageIO.read(new File(profile.getAvatar()));
        resource.setImage(image);
        add(new Image("avatar", resource)); 
      }
      catch (IOException e) {
        add(new Image("avatar"));
      }
    }
    
    /**
     * Add personal info.
     */
    private void addInfo() {
      personalItems.add(new CommonListItem("Screen name:", screenName));
      personalItems.add(new CommonListItem("Email:", emailAddress));
      personalItems.add(new CommonListItem("Name:", fullName));
      if (!("".equals(gender))) {
        personalItems.add(new CommonListItem("Gender:", gender));
      }
      if (!("".equals(userLocation))) {
        personalItems.add(new CommonListItem("Location:", userLocation));
      }
      if (!("".equals(contact))) { 
        personalItems.add(new CommonListItem("Contact:", contact));
      }
      add(new TableContentFragment("personalInfo", personalItems));
    }
  }
  
  /**
   * Text box fragment class for paragraph listings.
   * @author Anthony Du
   *  
   */
  public class TextBoxFragment extends Fragment {
    /** Support serialization. */
    private static final long serialVersionUID = 1L;
    
    /** 
     * Text box fragment constructor.
     * @param id fragment id
     * @param text text information
     */
    public TextBoxFragment(String id, String text) {
      super(id, "textBoxFragment", ProfilePanel.this);
      add(new Label("textLabel", text));
    }
  }
  
  /**
   * Table Content Fragment class for common table listings of common items.
   * @author Anthony Du
   *
   */
  public class TableContentFragment extends Fragment {
    /** Support serialization. */
    private static final long serialVersionUID = 1L;
    
    /**
     * Table content fragment constructor.
     * @param id fragment id
     * @param items list of items
     */
    public TableContentFragment(String id, List<CommonListItem> items) {
      super(id, "tableContentFragment", ProfilePanel.this);
      add(getListView("tableRow", items));
    }

    /**
     * Generate and return the list view of items.
     * @param id list view id
     * @param items list of items
     * @return ListView list view of items
     */
    private ListView getListView(String id, List<CommonListItem> items) {
      ListView lv = new ListView(id, items) {
        /** Support serialization. */
        private static final long serialVersionUID = 1L;

        @Override
        protected void populateItem(ListItem item) {
          CommonListItem listItem = (CommonListItem)item.getModelObject();
          item.add(new Label("label", listItem.getLabel()));
          item.add(new Label("labelValue", listItem.getValue()));
        }
      };
      return lv;
    }
  }
  
  /**
   * CommonListItem class for building common list items.
   * @author Anthony Du
   *
   */
  public static class CommonListItem implements Serializable {
    /** Support serialization. */
    private static final long serialVersionUID = 1L;
    /** Item List label. */
    private String label = "";
    /** Item List label value. */
    private String value = "";
    /**
     * CommonListItem constructor.
     * @param label item's label
     * @param value item's value
     */
    public CommonListItem(String label, String value) {
      this.label = label;
      this.value = value;
    }
    
    /**
     * Returns label.
     * @return label
     */
    public String getLabel() {
      return label;
    }
    
    /**
     * Returns value.
     * @return value
     */
    public String getValue() {
      return value;
    }
  }
}
